StdCmds.OpenBrowser('Form/Map', 'Map to the Form subsystem')
Helvetica
StdCmds.OpenDoc('Obx/Mod/Twins')
DevCommanders.StdViewDesc
DevCommanders.ViewDesc
Oberon by Example: ObxTwins
ObxTwins is an example of a container view. Container views come in mainly two flavours: dynamic containers, which may contain an arbitrary and variable number of other views, which may be of any type. On the other hand, static containers contain an exactly predetermined number of views, and often the types and layout of these views is predetermined and not editable.
Our example shows the implementation of a static container, for an example of a dynamic container please see the
subsystem
ObxTwins implements a view which shows two subviews, a smaller one at the top, and a larger one at the bottom. Both of these views are editable text views; one of them is the current focus. The two views are not treated exactly in the same way: the top view has a fixed height, while the bottom view can be arbitrarily high. The vertical scroll bar of the twin view always shows the state of the bottom view, even if the top view is focused. There are various ways in which such a twin view can be used. For example, the top view might be used to hold a database query, whose result appears in the bottom view. Or a "chatter" application could be written, with one's own input in the top view, and the partner's messages in the bottom view.
The example uses the normal decomposition of an editor into a view and a model component. The view only contains the model and an indication whether the top or the bottom view are currently focused. The model contains several immutable fields (i.e. fields which are defined once and then never altered again). These fields determine the layout of the views, and they anchor the two contained views.
The views are not directly anchored in the model; instead, two contexts are provided. Such a context contains a view, its size, and the models's domain. A context's view contains a backpointer to the context (aView.context), i.e. a view can access its environment via this pointer; e.g. in order to ask what its current size is, or in order to ask for a size change or other favour from its container.
The most interesting part of this example is the view's HandleCtrlMsg procedure. It handles incoming messages in three different ways. Normally, it just lets the message forward to its currently focused subview. Messages which are related to scrolling (Controllers.PollSectionMsg, Controllers.ScrollMsg, Controllers.PageMsg) are always forwarded to the bottom view, independent of the current focus. And finally, cursor messages (Controllers.CursorMessage) are always forwarded to the view under the cursor position.